using Consul;
using hao_Common.Consul.HostedServices;
using hao_Common.Consul.Options;
using hao_Common.Consul.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace hao_Common.Consul.Extensions
{
    /// <summary>
    /// 服务集合扩展类
    /// 提供 Consul 服务注册的扩展方法
    /// </summary>
    public static class ServiceCollectionExtensions
    {
        /// <summary>
        /// 添加 Consul 相关服务到依赖注入容器
        /// 包括配置绑定、Consul 客户端、服务注册、服务发现等功能
        /// </summary>
        /// <param name="services">服务集合</param>
        /// <param name="configuration">配置对象，用于读取 Consul 配置</param>
        /// <returns>返回服务集合，支持链式调用</returns>
        public static IServiceCollection AddConsul(this IServiceCollection services, IConfiguration configuration)
        {
            // 绑定 Consul 配置选项到 ConsulOptions 类
            // 从配置文件的 "Consul" 节点读取配置并注册到 DI 容器
            services.Configure<ConsulOptions>(options =>
            {
                configuration.GetSection(ConsulOptions.SectionName).Bind(options);
            });

            // 注册 Consul 客户端
            // 使用单例模式，根据配置创建 ConsulClient 实例
            services.AddSingleton<IConsulClient>(provider =>
            {
                var consulOptions = provider.GetRequiredService<Microsoft.Extensions.Options.IOptions<ConsulOptions>>().Value;
                return new ConsulClient(config =>
                {
                    config.Address = new Uri($"http://{consulOptions.Host}:{consulOptions.Port}");
                    config.Datacenter = consulOptions.Datacenter;
                });
            });

            // 注册 Consul 服务注册器
            // 负责服务的注册和注销操作
            services.AddSingleton<IConsulServiceRegistry, ConsulServiceRegistry>();

            // 注册服务发现组件
            // 负责从 Consul 中发现和获取健康的服务实例
            // 负责从 Consul 中发现和获取健康的服务实例
            services.AddSingleton<IServiceDiscovery, ConsulServiceDiscovery>();

            // 注册 Consul 后台服务
            // 在应用启动时自动注册服务，在应用停止时自动注销服务
            services.AddHostedService<HostedServices.ConsulHostedService>();

            return services;
        }
    }
}